Claude Code 攻略 1.4 - Prompt Engineering 实战指南

2025-12-22 | 104分钟 | yrobot | Prompt Engineering,提示工程,Few-shot Learning,Chain-of-Thought,AI 交互,Claude Code,LLM 优化

需求表达的艺术

在使用 Claude Code 的过程中,我经常遇到这样的情况:同样的需求,有时候 AI 给出的方案非常精准,有时候却只能给一些模糊的建议。比如,我想重构一段代码,直接说"重构这段代码",AI 可能只做一些表面的优化;但如果我说"作为架构师,审查这段代码的设计问题,并给出重构方案",AI 会从更高的层次思考,给出系统性的改进建议。

与 AI 对话不只是"说清楚需求"这么简单,如何表达需求、如何引导 AI 的思考方向,都会显著影响输出质量。这就是 Prompt Engineering(提示工程)要解决的问题。

在上一篇攻略中,我们学习了上下文工程,强调"输入决定输出质量"。如果说上下文工程关注的是"提供什么信息",那么 Prompt Engineering 关注的就是"如何表达需求"。两者的关系可以这样理解:

上下文工程:提供完整的视野(代码、文档、项目配置)
           ↓
Prompt Engineering:表达清晰的意图(我想要什么、怎么做)
           ↓
       高质量输出

这篇文章,我会系统地介绍 Prompt Engineering 的 6 个核心技巧,帮助你在使用 Claude Code 时更高效地表达需求。

核心技巧 1:提供充分上下文

什么是"充分"?

不是越多越好,而是让 LLM 能够构建完整推理链所需的最小信息集。

对比案例

场景:Next.js 页面加载慢

Prompt A(信息不足):

我的 Next.js 页面加载很慢,帮我分析原因。

LLM 的推理链(卡住):

提取问题:页面加载慢
↓
检索知识:什么会导致页面慢?
↓
【卡住】没有具体信息,只能列举所有可能性
↓
输出通用答案:可能是请求慢、渲染慢、资源加载慢...

Prompt B(充分上下文):

我的 Next.js 页面 `/dashboard` 加载很慢(首屏 5 秒)。

观察到的现象:
- Network 面板显示一个 API 请求耗时 3.5 秒
- 该请求是 `/api/users`,返回 10MB 数据
- 页面渲染时使用了 `map()` 遍历所有数据

请分析可能的性能瓶颈,并建议优化方案。

LLM 的推理链(完整):

提取问题:页面加载慢(5秒)
↓
检索上下文:API 请求 3.5 秒 + 返回 10MB + 前端 map() 遍历
↓
推理:3.5秒占了总时长的 70% → 主要瓶颈在请求
↓
深入推理:10MB 数据量过大 + 前端全量渲染 → 双重问题
↓
输出针对性方案:
  1. 后端分页/过滤,减少数据量
  2. 前端虚拟滚动,只渲染可见部分
  3. 考虑增量加载

Prompt B 提供了哪些关键信息?

  1. 具体位置/dashboard 页面(不是泛泛的"页面")
  2. 可量化指标:5 秒、3.5 秒、10MB(让问题可度量)
  3. 关键证据:API 请求、数据量、前端处理方式(推理的线索)
  4. 明确期望:分析瓶颈 + 优化方案(输出方向)

使用场景

  • 适用:几乎所有场景,这是最基础的技巧
  • 特别重要:问题诊断、性能优化、Bug 修复

核心技巧 2:明确角色与目标

角色设定的本质价值

角色设定不是形式主义,而是触发 LLM 的专业知识检索系统性思考

对比案例

场景:代码重构

Prompt A(无角色):

请帮我重构这段代码:

@components/UserList.tsx

要求:
- 提取重复逻辑
- 优化性能
- 遵循 React 最佳实践

AI 可能的输出:

  • 表面优化:提取几个函数、用 useCallback 包裹
  • 缺乏深度:只关注代码层面,不考虑架构

Prompt B(指定角色):

作为一位资深的 React 架构师,请审查并重构这段代码:

@components/UserList.tsx

审查重点:
- 识别代码异味和性能瓶颈
- 评估组件职责是否单一
- 建议架构层面的改进

要求:
- 先指出问题,再给出重构方案
- 解释每个改动的原因
- 遵循 React 最佳实践

AI 可能的输出:

  • 系统性分析:从架构、职责划分、性能等多个维度审查
  • 专业深度:提出状态提升、组件拆分、自定义 Hook 等架构级建议
  • 说明原因:解释为什么这样改进

何时需要角色设定?

需要:

  1. 需求不明确,需要专业视角补充
  2. 需要系统性思考,而非点状执行
  3. 需要特定领域的专业知识

不需要:

  1. 需求非常明确,无需补充
  2. 简单的执行类任务
  3. 你已经提供了详细的规范

实用原则

判断是否需要角色设定,问自己:

  1. 我的需求是否足够明确?(不明确 → 需要角色)
  2. 我需要 AI "照单执行"还是"发挥专业判断"?(后者 → 需要角色)
  3. 这个任务是否需要专业知识?(需要 → 指定专业角色)

核心技巧 3:使用示例引导(Few-shot Learning)

你是否遇到过这样的情况:让 AI 写 Git commit message,结果每次格式都不一样,有时是"修复bug",有时是"Fix: 修复了登录问题",有时又是"修复登录功能的bug"。你明明说了要求,但 AI 总是理解偏差。

这是因为规则描述是抽象的,AI 需要"推断"你的标准。而给出具体示例,AI 可以直接"复制"模式。

规则 vs 示例:LLM 的视角

规则描述(抽象):

"使用动词开头,说明改动的原因"

LLM 思考:
add? adding? added? 还是 adds?
原因是指什么原因?
→ LLM 需要"推断"你的标准

具体示例(模式):

✅ 好的示例:
- "Add: 新增用户偏好保存到 localStorage"
- "Fix: 修复移动端导航栏遮挡内容的问题"

LLM 识别:
动词原形 + 冒号 + 空格 + 中文描述
→ LLM 直接"复制"这个模式

关键差异:

  • 规则 = 让 AI 理解抽象概念,然后生成
  • 示例 = 让 AI 识别具体模式,然后模仿

LLM 更擅长模式匹配,而非抽象推理。

正例 + 反例 = 明确边界

只有正例:

"Fix: 修复移动端导航栏遮挡内容的问题"

AI 学到:这样写是对的
但 AI 不知道:哪些写法是错的

正例 + 反例:

"Fix: 修复移动端导航栏遮挡内容的问题""Fix bug"(太模糊,没说清楚修了什么)
❌ "修改了 3 个文件"(关注点错误,应该说影响)

AI 学到:
- 这样写是对的
- 这样写是错的
→ 明确了"详细程度"的边界

实战案例

场景:为函数添加 JSDoc 注释

Prompt(Few-shot):

请为以下函数添加 JSDoc 注释。

## 风格要求
- 简洁实用,避免冗余描述
- 说明函数作用、参数含义、返回值
- 如果函数逻辑显而易见,注释可以更精简

## 参考示例

✅ 推荐风格:
/**
 * 计算两个数的和
 * @param {number} a - 第一个数
 * @param {number} b - 第二个数
 * @returns {number} 两数之和
 */
function add(a, b) {
  return a + b;
}

/**
 * 从数组中过滤出偶数
 * @param {number[]} arr - 原数组
 * @returns {number[]} 只包含偶数的新数组
 */
function filterEven(arr) {
  return arr.filter(n => n % 2 === 0);
}

❌ 避免:
/**
 * 这个函数用于处理内部的复杂逻辑并返回结果
 * @param {any} data - 数据
 * @returns {any} 结果
 */
function process(data) { ... }
// 问题:描述模糊,类型不明确

/**
 * 此函数接收一个数组作为参数,然后遍历数组中的每一个元素,
 * 对每个元素进行判断,如果是偶数则保留,最后返回一个新数组
 * @param {number[]} arr - 输入的数组参数
 * @returns {number[]} 返回过滤后的数组
 */
function filterEven(arr) { ... }
// 问题:过于冗余,实现细节不需要在注释中说明

## 目标函数

@utils/calculator.ts 中的所有函数

示例数量选择

1-shot(1 个示例):

  • 适合:简单模式、风格明确

Few-shot(2-3 个示例):

  • 适合:中等复杂度、需要展示变化

Many-shot(5+ 个示例):

  • 适合:复杂模式、需要覆盖多种情况
  • 注意:消耗更多 Token

原则:够用就好,不是越多越好。

使用场景

  • 风格对齐(代码注释、commit message、文档格式)
  • 格式规范(API 文档、测试用例)
  • 复杂模式识别(代码重构模式、命名规范)

核心技巧 4:要求推理过程(Chain-of-Thought)

为什么推理过程能降低 AI 幻觉?

直接给答案(无推理):

AI 思考过程(内部,你看不到):
检索知识 → [跳跃] → 给出结论

问题:中间的推理步骤被跳过,容易出现逻辑漏洞

展示推理过程:

AI 思考过程(外部,你能看到):
第 1 步:识别问题类型
第 2 步:列举可能原因
第 3 步:逐一分析概率
第 4 步:得出结论

效果:每一步都需要有依据,减少了"臆测"的空间

类比:学生做数学题

  • 直接写答案 → 容易算错
  • 写出推导步骤 → 每步都要自洽,错误率降低

Chain-of-Thought 的三个核心价值

1. 可解释性

  • 你知道 AI 是怎么得出结论的
  • 你可以判断这个推理是否靠谱
  • 你可以在推理的某一步介入修正

2. 可靠性

  • 强制 AI 展示中间步骤,减少"跳跃式推理"
  • 每一步都需要有依据,降低"编造"的概率
  • AI 在写推理过程时,会进行自我校验

3. 可迁移性

  • 你看到了 AI 的分析框架
  • 下次遇到类似问题,你可以套用这个框架
  • 从"依赖 AI"到"学会方法论"

实战案例

场景:React 组件频繁重渲染

Prompt(要求推理):

作为前端性能优化专家,请帮我分析并解决 React 组件的重渲染问题。

## 背景
项目:Next.js + React 18
问题组件:@components/UserList.tsx

观察到的现象:
- 滚动列表时页面卡顿
- 每次滚动触发 5-10 次 UserList 重渲染
- Console 日志显示频繁的 "UserList rendered"

## 分析要求

请按以下步骤分析,并展示每一步的推理过程:

**第 1 步:诊断重渲染原因**
- 检查 props 是否每次都是新引用(对象/数组/函数)
- 检查父组件是否频繁 setState
- 检查 context 是否不必要地更新
- 列出可能的原因,并说明判断依据

**第 2 步:定位触发点**
- 找出具体是哪个 props/state/context 导致重渲染
- 解释为什么这个变化会触发重渲染
- 评估这个重渲染是否必要

**第 3 步:设计优化方案**
- 列出 2-3 种可行的优化方案
- 对比各方案的优劣(效果/成本/风险)
- 推荐最佳方案并说明理由

**第 4 步:实施优化**
- 给出具体的代码修改
- 解释每个修改的原理
- 说明如何验证优化效果

## 工作流程

1. 先展示完整的分析思路(步骤 1-3)
2. 等我确认后,再实施优化(步骤 4)

使用场景

适用:

  • 复杂问题诊断
  • 技术选型
  • 架构设计
  • 代码优化

不适用:

  • 简单执行类任务
  • 明确答案的知识查询

实用技巧

技巧 1:明确要求推理步骤

不要:请分析一下这个问题
而是:请按以下步骤分析:1) ... 2) ... 3) ...

技巧 2:要求"解释推理过程" 常用话术:

  • "请解释你的思考过程"
  • "请说明每个建议的依据"
  • "请先分析,再给出结论"
  • "请展示你的推理链"

核心技巧 5:分步骤引导

假设你要做一个大规模的代码库重构,直接让 AI 一次性完成,结果改了几十个文件,运行测试发现到处都是错误,你不知道是哪一步出的问题。如果分步执行:先写测试 → 重构核心模块 → 验证 → 重构周边代码 → 最终验证,每一步都可控,出错了也容易定位。

这就是分步骤引导的价值:将复杂任务拆解为可控的小步骤。

与 Chain-of-Thought 的区别

Chain-of-Thought:要求 AI 展示思考过程 分步骤引导:将任务本身拆解为多个执行步骤

类比:

  • Chain-of-Thought = 让学生展示解题思路
  • 分步骤引导 = 把大作业拆成小任务

步骤性质不同

Chain-of-Thought 的步骤 = 思维步骤

步骤 1:识别问题 → 思考环节
步骤 2:分析原因 → 思考环节
步骤 3:设计方案 → 思考环节
步骤 4:实施优化 → 执行环节

分步骤引导的步骤 = 执行步骤

步骤 1:重构状态管理 → 执行环节
步骤 2:优化渲染 → 执行环节
步骤 3:添加监控 → 执行环节

两阶段策略:组合使用

当你对需求没有完整概念时,可以先用 Chain-of-Thought 分析,再用分步骤引导执行。

实战案例:博客全文搜索功能

阶段 1:Chain-of-Thought(分析决策)

作为全栈架构师,请帮我设计博客的全文搜索功能。

请按以下思路分析:

1. **技术方案对比**
   - 列出主流方案(Algolia、ElasticSearch、自建索引等)
   - 分析各方案的优劣(成本、性能、维护难度)

2. **适配我的场景**
   - 我的博客:Next.js + Markdown 文件
   - 文章数量:约 100 篇,增长缓慢
   - 预算有限,希望自托管

3. **推荐方案**
   - 基于分析给出推荐
   - 说明推荐理由
   - 列出实施的关键步骤

阶段 2:分步骤引导(执行实施)

很好!请按你推荐的方案,分步实施:

## 第 1 步:构建索引脚本
- 创建 `scripts/build-search-index.js`
- 扫描 @_blogs/ 目录
- 提取每篇文章的:title、description、content(前 200 字)
- 输出 `public/search-index.json`

## 第 2 步:集成到构建流程
- 在 `package.json` 的 build 脚本中添加索引生成
- 确保每次构建都更新索引

## 第 3 步:实现搜索组件
- 创建 `@components/Search.tsx`
- 使用 Fuse.js 加载索引
- 实现搜索逻辑和结果展示

## 第 4 步:添加到导航栏
- 在 `@components/Navbar.tsx` 中引入 Search 组件
- 添加快捷键支持(Cmd+K)

每完成一步,我会验证后再继续下一步。

如何选择?

使用 Chain-of-Thought 当:

  • 你不确定怎么做
  • 需要 AI 的专业判断
  • 想学习 AI 的思考方式

使用分步骤引导当:

  • 任务复杂,需要拆解
  • 步骤有依赖关系
  • 想控制执行节奏

组合使用当:

  • 复杂且不确定的任务
  • 先分析决策,再执行实施

核心技巧 6:设定输出格式

你让 AI 分析代码问题,它回复了一大段话:"这段代码存在性能问题,建议使用 useCallback,另外 key 也缺失,还有状态管理可以优化..."。你读完还要自己梳理:哪些问题优先?哪些可以缓缓?

如果你要求 AI 用表格输出:

问题 优先级 影响
缺少 useCallback P0 性能
缺少 key P0 功能
状态管理混乱 P1 可维护性

一眼就能看出优先级,直接决策。这就是设定输出格式的价值。

为什么格式化能强制 AI 更全面?

自由格式(无结构):

"请分析这段代码的问题"

AI 思考过程:
想到什么说什么 → 可能遗漏某些维度

结构化格式(有框架):

"请分析:
| 问题 | 严重性 | 影响 |"

AI 思考过程:
每个问题都要填三个字段 → 强制思考"这个问题的严重性和影响是什么"
表格格式 → 暗示需要列举多个问题,不能只说一个

类比:

  • 自由作文 vs 填空题
  • 自由发言 vs 结构化汇报

效果:结构就是一种"检查清单",确保不遗漏关键信息。

三个核心价值

1. 可读性 - 快速提取关键信息

对比:

无格式:"代码存在性能问题,建议使用 useCallback,另外 key 也缺失..."
→ 需要自己梳理:哪些是问题?哪些优先?

有格式:
| 问题 | 优先级 |
|------|--------|
| 缺少 useCallback | P0 |
| 缺少 key | P0 |
| 状态管理混乱 | P1 |
→ 一眼看出优先级,直接决策

2. 可用性 - 便于后续处理

表格/JSON 格式的输出可以:
- 直接参考执行("根据表格中 P0 优先级的问题..."- 导入工具处理(任务管理、自动化脚本)

3. 完整性 - 强制系统性思考

结构化格式会暗示需要覆盖多个维度,减少遗漏。

常用输出格式模板

1. 表格格式(对比分析)

| 维度 | 方案 A | 方案 B | 推荐 |
|------|--------|--------|------|

适用:技术选型对比、方案优劣分析

2. 检查清单(完整性保证)

## 功能检查
- [ ] 核心功能
- [ ] 边界情况
- [ ] 错误处理
- [ ] 性能优化

适用:代码审查、功能验收

3. 分级列表(优先级排序)

## P0(必须修复)
1. [问题]

## P1(建议修复)
1. [问题]

适用:Bug 修复、性能优化

4. 结构化文档(标准格式)

## 概述
## 核心内容
## 示例
## 注意事项

适用:API 文档、技术规范

5. JSON/YAML(可编程处理)

{
  "tasks": [...],
  "dependencies": [...],
  "estimatedTime": "..."
}

适用:集成到工作流、自动化处理

通用 Prompt 范式

基于以上 6 个核心技巧,这里提供一个通用的 Prompt 范式。根据任务复杂度,你可以选择性使用各个模块。

[一句话概括任务目标]

## 背景(可选,复杂任务建议加上)
- 为什么需要这个功能?
- 要解决什么问题?
- 当前的痛点是什么?

## 文件与位置
- 新建:`@path/to/NewFile.tsx`
- 修改:`@path/to/ExistingFile.tsx` 中的 `xxx` 函数
- 引入:在 `@path/to/Consumer.tsx` 中使用

## 功能需求
1. 核心功能点 1
   - 具体行为描述
   - 关键算法/逻辑(如有)
2. 核心功能点 2
   - ...

## 技术规范
- 使用的技术栈/库
- 代码风格:参考 `@STYLE_GUIDE.md`
- 命名约定:驼峰式/下划线等
- 性能要求(如有)

## 约束条件(可选)
- 必须兼容 xxx
- 不能修改 xxx 接口
- 必须使用 xxx 库

## 边界情况(关键场景,不求全但求准)
- 空数据/异常数据如何处理
- 用户异常操作如何响应
- 移动端/桌面端差异
- 性能边界(如大数据量)

## 测试用例/示例(可选但推荐)
- 输入 A → 预期输出 B
- 场景 X → 预期行为 Y

## 预期输出
- [ ] 直接给出完整代码
- [ ] 先给方案,待确认后实现
- [ ] 使用 Plan Mode,先规划再执行
- [ ] 给出 2-3 种方案对比

各模块的核心作用

模块 作用 何时必需
背景 帮助 AI 理解上下文,做更好决策 复杂任务、需要技术选型
文件位置 明确操作范围,避免歧义 几乎所有代码任务
功能需求 明确要实现什么 所有任务
技术规范 约束实现方式,保证一致性 团队协作、有规范要求
约束条件 避免 AI "自由发挥"触碰红线 有技术/业务限制
边界情况 提醒关键场景,提升代码健壮性 生产代码
测试用例 明确验收标准,便于验证 逻辑复杂的功能
预期输出 控制 AI 工作流程 不确定/复杂任务

快速检查清单

写完 Prompt 后,问自己:

  • AI 能否理解我要做什么?(目标明确)
  • AI 知道在哪里做吗?(位置明确)
  • AI 知道如何验证做对了吗?(标准明确)
  • 关键约束我都说清楚了吗?(边界明确)
  • 我期望 AI 先规划还是直接干?(流程明确)

6 个核心技巧总结

技巧 核心作用 适用场景
1. 提供充分上下文 让 AI 能推理 几乎所有场景
2. 明确角色与目标 触发专业知识、补充需求 需求不明确时
3. 使用示例 模式学习、风格对齐 需要特定格式/风格
4. 要求推理过程 降低幻觉、可解释性 复杂决策、问题诊断
5. 分步骤引导 拆解任务、控制节奏 复杂任务、有依赖
6. 设定输出格式 提升可读性、完整性、可用性 需要结构化输出

核心原则与实践

Prompt Engineering 不是玄学,而是基于 LLM 工作机制的科学方法。核心原则:

  1. 信息充分:提供 AI 构建推理链所需的关键信息
  2. 表达清晰:使用结构化、明确的语言表达需求
  3. 引导思考:通过示例、步骤、格式引导 AI 的思考方向
  4. 控制流程:明确期望的工作流程和输出格式

在实际使用中,你可以:

  • 从通用 Prompt 范式开始,根据任务选择性使用各个模块
  • 遇到复杂任务,采用两阶段策略:先 Chain-of-Thought 分析,再分步执行
  • 用快速检查清单验证 Prompt 质量

Prompt Engineering 是一项需要持续实践的技能。在使用 Claude Code 时,有意识地应用这些技巧,观察输出质量的变化,逐步建立自己的 Prompt 模式库。

下一篇攻略,我们会深入学习 Claude Code 的整体架构与核心特性,理解它与其他 AI 工具的本质差异。